package com.zbkj.service.sfexpress;

import cn.hutool.core.util.IdUtil;
import com.zbkj.service.sfexpress.util.VerifyCodeUtil;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import feign.codec.Encoder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.http.MediaType;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

/**
 * @author lijiajia
 * @date 2019/6/21 15:55
 */
@Slf4j
public class SFFeignAuthConfiguration {

    @Bean
    public RequestInterceptor requestInterceptor(
            Encoder encoder,
            @Value("${express.sf.client-code:HJGWHHXNBTPE}") String clientCode,
            @Value("${express.sf.check-code:3tcBbQCU4axGzmvrO4wN5PgTgbR4805J}") String checkCode) {

//        Encoder bean = SpringUtil.getBean(Encoder.class);
//        System.out.println(bean);
        return new FeignBasicAuthRequestInterceptor(encoder, clientCode, checkCode);
    }

    private static class FeignBasicAuthRequestInterceptor implements RequestInterceptor {

        private final Encoder formEncoder;
        private final String clientCode;
        private final String checkCode;

        public FeignBasicAuthRequestInterceptor(Encoder formEncoder, String clientCode, String checkCode) {
            this.formEncoder = formEncoder;
            this.clientCode = clientCode;
            this.checkCode = checkCode;
        }

        @Override
        public void apply(RequestTemplate template) {
            try {
                SFServiceCode annotation = template.methodMetadata().method().getAnnotation(SFServiceCode.class);
                if (annotation == null) {
                    throw new RuntimeException("SFServiceCode注解不能为空");
                }
                // 设置请求头
                template.removeHeader("Content-Type");
                template.header("Content-Type", MediaType.APPLICATION_FORM_URLENCODED_VALUE);

                // 设置请求体，这里假设使用Map作为表单数据
//                Map<String, Object> formData = new MultiValueMap<>(10);
                MultiValueMap<String, Object> formData = new LinkedMultiValueMap<>();

                String timeStamp = String.valueOf(System.currentTimeMillis());
                String requestId = IdUtil.fastSimpleUUID();
                String msgData = template.requestBody().asString();
                String serviceCode = annotation.value().getCode();

                // 顾客编码 ，对应丰桥上获取的clientCode
                formData.add("partnerID", clientCode);
                // 请求 ID
                formData.add("requestID", requestId);
                // 接口服务码
                formData.add("serviceCode", serviceCode);
                // 时间戳
                formData.add("timestamp", timeStamp);
                // 请求主体
                formData.add("msgData", msgData);
                // 加密处理
                formData.add("msgDigest", this.getMsgDigest(msgData, timeStamp, checkCode));
                log.info("请求 MsgData： {}", msgData);
                // 使用Feign的FormEncoder编码器将Map转换为表单数据
                formEncoder.encode(formData, LinkedMultiValueMap.class, template);
            } catch (UnsupportedEncodingException e) {
                log.error("请求 SF 失败", e);
                throw new RuntimeException(e);
            }
        }

        public String getMsgDigest(String msgData, String timeStamp, String md5Key) throws UnsupportedEncodingException {
            return VerifyCodeUtil.md5EncryptAndBase64(URLEncoder.encode(msgData + timeStamp + md5Key, StandardCharsets.UTF_8.name()));
        }
    }
}
